package com.bah.tract.client.workstore.project;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.util.JAXBResult;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPFaultException;

import org.w3c.dom.Element;

import com.bah.tract.client.workstore.TaskProvider;
import com.bah.tract.service.StringProperty;
import com.bah.tract.service.Task;
import com.microsoft.schemas.office.project.server.webservices.project.DataStoreEnum;
import com.microsoft.schemas.office.project.server.webservices.project.Project;
import com.microsoft.schemas.office.project.server.webservices.project.ProjectSoap;
import com.microsoft.schemas.office.project.server.webservices.project.ReadProjectListResponse.ReadProjectListResult;
import com.microsoft.schemas.office.project.server.webservices.project.ReadProjectResponse.ReadProjectResult;
import com.microsoft.schemas.office.project.server.webservices.projectdataset.ProjectDataSet;
import com.microsoft.schemas.office.project.server.webservices.projectdataset.ProjectDataSet.Assignment;
import com.microsoft.schemas.office.project.server.webservices.resource.Resource;
import com.microsoft.schemas.office.project.server.webservices.resource.ResourceSoap;

public class ProjectTaskProvider implements TaskProvider {

	private String mProjectName;

	private String mPWAURL;

	private long storeId;

	public ProjectTaskProvider(Map<String, Object> properties, long id) {
		// Need to know the URL to the project server.
		mPWAURL = (String) properties.get("projectUrl");
		// Need to know the project's name.
		mProjectName = (String) properties.get("label");
		storeId = id;
	}

	@Override
	public List<Task> getTasks() {
		List<Task> userTasks = new ArrayList<Task>();
		ResourceSoap resourceWs = new Resource().getResourceSoap();
		BindingProvider bp = (BindingProvider) resourceWs;
		bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
				mPWAURL + "/_vti_bin/psi/Resource.asmx");
		ProjectSoap projectWs = new Project().getProjectSoap();
		bp = (BindingProvider) projectWs;
		bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
				mPWAURL + "/_vti_bin/psi/Project.asmx");
		try {
			JAXBContext context = JAXBContext
					.newInstance("com.microsoft.schemas.office.project.server.webservices.projectdataset");
			ReadProjectListResult projectList = projectWs.readProjectList();
			Element elem = (Element) projectList.getAny();
			elem = (Element) elem.getFirstChild();
			Transformer t = TransformerFactory.newInstance().newTransformer();
			JAXBResult result = new JAXBResult(context);
			t.transform(new DOMSource(elem), result);
			ProjectDataSet dataSet = (ProjectDataSet) result.getResult();
			String projectId = null;
			// Find the project's id
			for (Object obj : dataSet.getProjectOrTaskOrProjectResource()) {
				if (obj instanceof com.microsoft.schemas.office.project.server.webservices.projectdataset.ProjectDataSet.Project) {
					com.microsoft.schemas.office.project.server.webservices.projectdataset.ProjectDataSet.Project p = (com.microsoft.schemas.office.project.server.webservices.projectdataset.ProjectDataSet.Project) obj;
					if (mProjectName.equals(p.getPROJNAME())) {
						projectId = p.getPROJUID();
					}
				}
			}
			ReadProjectResult res = projectWs.readProject(projectId,
					DataStoreEnum.PUBLISHED_STORE);
			elem = (Element) res.getAny();
			elem = (Element) elem.getFirstChild();
			result = new JAXBResult(context);
			t.transform(new DOMSource(elem), result);
			dataSet = (ProjectDataSet) result.getResult();
			Map<String, ProjectDataSet.Task> tasks = new HashMap<String, ProjectDataSet.Task>();
			Map<String, String> assignments = new HashMap<String, String>();
			String userId = resourceWs.getCurrentUserUid();
			for (Object obj : dataSet.getProjectOrTaskOrProjectResource()) {
				if (obj instanceof ProjectDataSet.Task) {
					ProjectDataSet.Task task = (ProjectDataSet.Task) obj;
					tasks.put(task.getTASKUID(), task);
				} else if (obj instanceof Assignment) {
					Assignment a = (Assignment) obj;
					if (userId.equals(a.getRESUID())) {
						assignments.put(a.getTASKUID(), a.getASSNUID());
					}
				}
			}
			for (String assignment : assignments.keySet()) {
				ProjectDataSet.Task task = tasks.get(assignment);
				Task tractTask = new Task();
				// This is the assignment number because assignments are what
				// status is reported against not tasks.
				tractTask.getIdentifyingProperty().add(
						new StringProperty("taskNumber", assignments
								.get(assignment)));
				// Make sure that the task provides all of the information
				// necessary to report status on the task.
				tractTask.getDescriptiveProperty().add(
						new StringProperty("pwaURL", mPWAURL));
				tractTask.getDescriptiveProperty().add(
						new StringProperty("projectId", projectId));
				tractTask.setType("MSProjectTask");
				tractTask.setLabel(task.getTASKNAME());
				tractTask.setStoreId(storeId);
				tractTask.setDescription(task.getTASKNAME());
				userTasks.add(tractTask);
			}

		} catch (SOAPFaultException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return userTasks;
	}
}
